﻿--[[
	Widget name	  	CodeHelper
	Author     	 	Kurapica
--]]

-- CodeHelper
do
	IGAS:NewAddon("IGAS_Studio")	

    ------------------------------------------------------
	-- _CodeSmartHelper
	------------------------------------------------------
	local _CodeSmartHelper = CreateFrame("EditBox", "IGAS_Studio_CodeHelper", coreF)
	_CodeSmartHelper:SetBackdropColor(0, 0, 0, 1)
	_CodeSmartHelper:SetTextInsets(0, 0, 0, 0)
	_CodeSmartHelper.JustifyH = "LEFT"
	_CodeSmartHelper.JustifyV = "MIDDLE"
	_CodeSmartHelper.FontObject = "GameFontNormalSmall"
	_CodeSmartHelper.FrameStrata = "TOOLTIP" 
	_CodeSmartHelper.MouseEnabled = true
	_CodeSmartHelper.AutoFocus = true
	_CodeSmartHelper.Width = 180
	_CodeSmartHelper.Height = 26
	_CodeSmartHelper.Visible = false
	
	GRN    ='|cff20ff20'
	YEL    ='|cffffff00'
	RED    ='|cffff0000'
	WHT    ='|cffffffff'
	BLU    ='|cff8888ff'
	DRKBLU ='|cff1b0495'
	ORN    ='|cffff9C00'
	GRY    ='|cffA0A0A0'

	-- Create List
	local _List = CreateFrame("List", "List", _CodeSmartHelper)
	_List.FrameStrata = "TOOLTIP"
	_List.DisplayItemCount = 8
	
	-- GameTooltip
	local _GameTooltip = CreateFrame("GameTooltip", "GameTooltip", coreF, "GameTooltipTemplate")
	local _Timer = CreateFrame("Timer", "FadeTimer", _GameTooltip)
	
    -- Scripts
	local function GetIndex(list, name, sIdx, eIdx)
		if not sIdx then
			if not next(list) then
				return nil
			end
			sIdx = 1
			eIdx = getn(list)
		end
		if sIdx == eIdx then
			if sIdx > 1 then
				return sIdx - 1
			else
				return nil
			end
		end
		local f = floor((sIdx + eIdx) / 2)
		if sortFunc(list[f], name) then
			if not sortFunc(list[f + 1], name) then
				return f
			else
				return GetIndex(list, name, f + 1, eIdx)
			end
		elseif strupper(list[f]) == strupper(name) then
			return GetIndex(list, name, f, f)
		else
			return GetIndex(list, name, sIdx, f)
		end
	end

	function _List:OnItemChoosed(key, text)
		self.Parent.Text = text
	end
	
	function _List:OnItemDoubleClick(key, text)
		self.Parent.Text = text
		self.Parent:Fire("OnEnterPressed")
	end

	function _CodeSmartHelper:OnShow()
		self.Text = ""
		_List:ClearAllPoints()
		if self:GetBottom() - _List.Height > 0 then
			_List:SetPoint("TOPLEFT", self, "BOTTOMLEFT")
			_List:SetPoint("TOPRIGHT", self, "BOTTOMRIGHT")
		else
			_List:SetPoint("BOTTOMLEFT", self, "TOPLEFT")
			_List:SetPoint("BOTTOMRIGHT", self, "TOPRIGHT")
		end
		_List:Refresh()
		_List:SelectItemByValue(nil)
		self:SetFocus()
	end
	
	function _CodeSmartHelper:OnCharComposition(char)
	    local list = _List.Items
	    local text = self:GetText()
		local i, name

		if not text or text == "" then
			return
		end
		
		i, name = next(list, GetIndex(list, text))
		while i do
			if strfind(strupper(name), strupper(text), 1, 1) == 1 then
				_List:SelectItemByIndex(i)
				self:SetText(name)
				if (self:IsInIMECompositionMode()) then
					self:HighlightText(strlen(text) - strlen(char), -1)
				else
					self:HighlightText(strlen(text), -1)
				end					
				return
			end
			i, name = next(list, i)
		end
	end

	function _CodeSmartHelper:OnChar(char)
		if ( not self:IsInIMECompositionMode() ) then
			self:Fire("OnCharComposition", char)
		end
	end

	function _CodeSmartHelper:OnEditFocusGained()
        self:HighlightText()
	end
	
	function _CodeSmartHelper:OnEditFocusLost()
		
	end
	
	function _CodeSmartHelper:OnTabPressed()
		self:Fire("OnEnterPressed")
	end
	
	function _CodeSmartHelper:OnEnterPressed()
        self:HighlightText(0, 0)
		
		-- Tooltip
		_GameTooltip:SetOwner(_CodeSmartHelper.__CodeHelper.__Script, "ANCHOR_NONE")
		_GameTooltip:ClearAllPoints()
		_GameTooltip.FrameLevel = _CodeSmartHelper.__CodeHelper.__Script.FrameLevel + 2
		if self:GetTop() < GetScreenWidth()/2 then
			_GameTooltip:SetPoint("BOTTOMLEFT", _CodeSmartHelper.__CodeHelper.__Script, "TOPLEFT", _CodeSmartHelper.__CodeHelper.__X+6, -_CodeSmartHelper.__CodeHelper.__Y + _CodeSmartHelper.__CodeHelper.__H)
		else
			_GameTooltip:SetPoint("TOPLEFT", _CodeSmartHelper.__CodeHelper.__Script, "TOPLEFT", _CodeSmartHelper.__CodeHelper.__X+6, -_CodeSmartHelper.__CodeHelper.__Y - _CodeSmartHelper.__CodeHelper.__H)
		end
		_GameTooltip:SetText(WHT..self.Text)
		
		local value = _List:GetSelectedItemValue()
		if value and type(value) == "table" then
			if value.Intro and type(value.Intro) == "string" then
				_GameTooltip:AddLine(BLU..((strtrim(value.Intro) ~= "" and value.Intro) or "No Introduction"))
			end
			
			if value.Body then
				if type(value.Body) == "string" then
					_GameTooltip:AddLine(GRN..((strtrim(value.Body) ~= "" and value.Body) or "No Body"))
				elseif type(value.Body) == "table" and (value.Body.Type == "number" or value.Body.Type == "string" or value.Body.Type == "boolean") then
					_GameTooltip:AddLine(GRN.."Type : "..value.Body.Type)
				elseif type(value.Body) == "table" and value.Body.Type == "enum" and value.Body.EnumType and type(value.Body.EnumType) == "table" then
					_GameTooltip:AddLine(GRN.."Type : Enum")
					for name in pairs(value.Body.EnumType) do
						if type(name) == "string" then
							_GameTooltip:AddLine(GRN.."    "..name)
						end
					end
				end
			end
		end
		
		_CodeSmartHelper.__CodeHelper.__Script:SetFocus()
		_CodeSmartHelper.__CodeHelper.__Script:Insert(self.Text)
		_CodeSmartHelper.Visible = false
		
		_Timer.Interval = 8
		_GameTooltip:Show()
	end
	
	function _CodeSmartHelper:OnEscapePressed()
        self:HighlightText(0, 0)
		self.Text = ""
		_CodeSmartHelper.__CodeHelper.__Script:SetFocus()
		_CodeSmartHelper.Visible = false
	end
	
	function _Timer:OnTimer()
		_Timer.Interval = 0
		_GameTooltip:FadeOut()
	end
	
    ------------------------------------------------------
	-- CodeHelper
	------------------------------------------------------
	local _WidgetName = "CodeHelper"
    local _Base = "VirtualUIObject"

	-- Scripts
	local function GatherBaseDB(lst, DB)
		if DB:GetBaseHelpDB() then
			GatherBaseDB(lst, DB:GetBaseHelpDB())
		end
		
		for name in pairs(DB) do
			lst[name] = true
		end
	end
	
	local function GatherHelpDB(self, DB)
		if not DB then
			return
		end
		
		self._DB = DB
		
		local lstName = {}
		
		GatherBaseDB(lstName, DB)
		
		local kList = {}
		
		for name in pairs(lstName) do
			tinsert(kList, name)
		end
		
		sort(kList)
		
		for _, name in pairs(kList) do
			tinsert(self.__Keys, DB[name])
			tinsert(self.__Items, name)
		end
	end

	-- _ScriptType
	local _ScriptType = {
	}
	
	-- Function
	local _Function = {
        -- Dispose, release resource
        ["Dispose"] = function(self)
            if _CodeSmartHelper.__CodeHelper == self then
				_CodeSmartHelper.Visible = false
				_CodeSmartHelper:ClearAllPoints()
				_CodeSmartHelper.__CodeHelper = nil
			end
            
            -- Call super's dispose
			self:CallMethod(_Base, "Dispose")
        end,

		-- Gather
		["AddItem"] = function(self, key, item)
			tinsert(self.Keys, key)
			tinsert(self.Items, item)
		end,
		
		["Clear"] = function(self)
			wipe(self.Keys)
			wipe(self.Items)
		end,
		
		-- Show
		["Show"] = function(self, script, x, y, w, h)
			self.__Script = script
			self.__X = x
			self.__Y = y
			self.__W = w
			self.__H = h
			
			_CodeSmartHelper.__CodeHelper = self
			_CodeSmartHelper.Visible = false
			_CodeSmartHelper:ClearAllPoints()
			_CodeSmartHelper:SetPoint("TOPLEFT", self.__Script, "TOPLEFT", x+6, -y)
			
			_List.Keys = self.Keys
			_List.Items = self.Items
			
			_CodeSmartHelper.Visible = true
		end,
		
		-- Hide
		["Hide"] = function(self)
			if _CodeSmartHelper.__CodeHelper == self then
				_CodeSmartHelper.Visible = false
				_CodeSmartHelper.__CodeHelper = nil
			end
		end,
		
		-- IsShown
		["IsShown"] = function(self)
			return _CodeSmartHelper.Visible and _CodeSmartHelper.__CodeHelper == self
		end,
    }
    
	-- Property
	local _Property = {
        -- Text
		["Text"] = {
			["Set"] = function(self, text)
				self:SetText(text)
			end,
			
			["Get"] = function(self)
				return self:GetText()
			end,
            
			["Type"] = IGAS:GetPropertyType("string"),
		},
		-- Visible
		["Visible"] = {
			["Set"] = function(self, flag)
				if flag then
					self:Show()
				else
					self:Hide()
				end
			end,
			
			["Get"] = function(self)
				return self:IsShown()
			end,
			
			["Type"] = IGAS:GetPropertyType("boolean"),
		},
		-- Keys
		["Keys"] = {
			["Set"] = function(self, keys)
				if keys and type(keys) == "table" then
					self.__Keys = keys
				else
					self.__Keys = {}
				end
			end,
			["Get"] = function(self)
				self.__Keys = self.__Keys or {}
				return self.__Keys
			end,
			["Type"] = IGAS:GetPropertyType("table"),
		},
		-- Items
		["Items"] = {
			["Set"] = function(self, items)
				if items and type(items) == "table" then
					self.__Items = items
				else
					self.__Items = {}
				end
			end,
			["Get"] = function(self)
				self.__Items = self.__Items or {}
				return self.__Items
			end,
			["Type"] = IGAS:GetPropertyType("table"),
		},
		-- ItemCount
		["ItemCount"] = {			
			["Get"] = function(self)
				return getn(self.Keys)
			end,
            
			["Type"] = IGAS:GetPropertyType("number"),
		},
    }
    
    -- New    
    local function _New(name, parent, ...)
		local frame = CreateFrame(_Base,name,parent)
		
		frame.__Keys = {}
		frame.__Items = {}
		
		GatherHelpDB(frame, CreateHelpDB(...))

        return frame
    end
	
    local _WidgetInfo = {
        ["WidgetName"] = _WidgetName,
        ["Base"] = _Base,
        ["Function"] = _Function,
        ["Property"] = _Property,
        ["ScriptType"] = _ScriptType,
        ["New"] = _New,
    }
    
    Widget[_WidgetName] = IGAS:NewWidget(_WidgetInfo)
end